#include "thrdpool.h"
#include "t_net_epoll.h"
#include <sys/epoll.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static pthread_t ep_thrd;
static Thrd *thrdpool_obj;
// static int *epfd = NULL;
static int epfd;
#define EP_EVENTS 2048
void *do_epoll_wait(void *arg)
{

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

    int epoll_fd = *((int *)arg);
    struct epoll_event ep_ev[EP_EVENTS] = {0};
    int i = 0;
    int counts = 0;

    while (1)
    {
        counts = epoll_wait(epoll_fd, ep_ev, EP_EVENTS, -1);
        if (0 == counts)
        {
            continue;
        }
        if (0 > counts)
        {
            printf("epoll wait error\n");
            break;
        }
        for (i = 0; i < counts; ++i)
        {
            Ep_Data *data = (Ep_Data *)ep_ev[i].data.ptr;
            t_net_add(data);
        }
    }
    return (void *)0;
}

/*add to thrdpool*/
static int t_net_add(Ep_Data *data);

/*create epoll and epoll wait and work thrd create*/
int t_net_init(int epnum, int nthrd)
{

    if (0 > epnum)
    {
        return 1;
    }
    epfd = epoll_create(0);
    if (0 > epfd)
    {
        return 2;
    }
    thrdpool_obj = thrdpool_init(nthrd);
    if (!thrdpool_obj)
    {
        return 3;
    }
    int rc = pthread_create(&ep_thrd, NULL, do_epoll_wait, (void *)&epfd);
    if (rc)
    {
        return rc;
    }
    return 0;
}

int t_net_add_epoll(void *ep_ctx)
{
    if (!ep_ctx)
    {
        return 1;
    }

    struct epoll_event ev;
    Ep_Data *data = (Ep_Data *)ep_ctx;
    ev.data.ptr = ep_ctx;

    return epoll_ctl(epfd, EPOLL_CTL_DEL, data->fd, &ev);
}

int t_net_del_epoll(Ep_Data *ep_ctx)
{
    if (!ep_ctx)
    {
        return 1;
    }
    return epoll_ctl(epfd, EPOLL_CTL_DEL, ep_ctx->fd, NULL);
}
/*add to thrdpool*/
int t_net_add(Ep_Data *data)
{

    if (!data)
    {
        return 1;
    }

    Task task;
    task.ctx = &data->msg;
    task.handle = data->cb;
    task.fd = data->fd;
    return thrdpool_add(thrdpool_obj, &task);
}

int t_net_deinit()
{
    pthread_cancel(ep_thrd);
    pthread_join(ep_thrd, NULL);
    thrdpool_destory(thrdpool_obj);
    return 0;
}
